import React, { FC, ReactNode } from 'react';

type Iprops = {
  children: ReactNode;
  [propName:string]:unknown;
};

type StateType = {
  Component:FC|null
};

const asyncComponent = (loadComponent:() => Promise<any>):ReactNode => (
  class AsyncComponent extends React.Component<Iprops, StateType> {
    constructor(props:Iprops) {
      super(props);
      this.state = {
        Component: null,
      };
    }

    componentDidMount() {
      if (this.hasLoadedComponent()) {
        return;
      }

      loadComponent()
        .then((module) => module.default)
        .then((Component: FC) => {
          this.setState({ Component });
        })
        .catch((err: Error) => {
          console.error('Cannot load component in <AsyncComponent />');
          throw err;
        });
    }

    hasLoadedComponent() {
      const { Component } = this.state;
      return Component !== null;
    }

    render() {
      const { Component } = this.state;
      // eslint-disable-next-line react/jsx-props-no-spreading
      return (Component) ? <Component {...this.props} /> : null;
    }
  }
);

export default asyncComponent;
